package com.zf.bm.common.core.sys.web;

import com.zf.bm.common.core.base.entity.BaseEntity;
import com.zf.bm.common.core.sys.dto.MenuDTO;
import com.zf.bm.common.utils.Collections3;
import com.zf.bm.common.utils.StringUtil;
import com.zf.bm.common.validator.BeanValidators;
import com.zf.bm.vo.MenuMetaVo;
import com.zf.bm.vo.MenuVo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.util.*;

@Slf4j
public abstract class BaseController {

    /**
     * 日志对象
     */
    protected Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 管理基础路径
     */
    @Value("${adminPath}")
    protected String adminPath;
    @Value("${sys.def.pwd}")
    protected String defPwd;
    //是否启用ROOT
    @Value("${sys.root}")
    protected boolean root;


    /**
     * 验证Bean实例对象
     */
    @Autowired
    protected Validator validator;


    /**
     * 服务端参数有效性验证
     *
     * @param object 验证的实体对象
     * @param groups 验证组
     * @return 验证成功：返回true；严重失败：将错误信息添加到 message 中
     */
    protected boolean beanValidator(Object object, Class<?>... groups) {
        try {
            BeanValidators.validateWithException(validator, object, groups);
        } catch (ConstraintViolationException ex) {
            List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
            list.add(0, "数据验证失败：");
            return false;
        }
        return true;
    }

    protected <T extends BaseEntity<T>> T newInstance(T entity, Class<T> clazz) {
        if (Objects.isNull(entity)) {
            try {
                return clazz.newInstance();
            } catch (Exception e) {
                log.error("exception:",e);
            }
        }
        return entity;

    }

    public Map<String, Object> buildTree(List<MenuDTO> menuDTOS) {
        List<MenuDTO> trees = new ArrayList<MenuDTO>();
        for (MenuDTO menuDTO : menuDTOS) {
            if ("0".equals(menuDTO.getPid().toString())) {
                trees.add(menuDTO);
            }
            for (MenuDTO it : menuDTOS) {
                if (it.getPid().equals(menuDTO.getId())) {
                    if (menuDTO.getChildren() == null) {
                        menuDTO.setChildren(new ArrayList<MenuDTO>());
                    }
                    menuDTO.getChildren().add(it);
                }
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("content", trees.size() == 0 ? menuDTOS : trees);
        map.put("totalElements", menuDTOS != null ? menuDTOS.size() : 0);
        return map;
    }

    public List<MenuVo> buildMenus(List<MenuDTO> menuDTOS) {
        List<MenuVo> list = new LinkedList<>();
        menuDTOS.forEach(menuDTO -> {
                    if (menuDTO != null) {
                        List<MenuDTO> menuDTOList = menuDTO.getChildren();
                        MenuVo menuVo = new MenuVo();
                        menuVo.setId(menuDTO.getId());
                        menuVo.setPId(menuDTO.getPid());
                        menuVo.setName(menuDTO.getName());
                        menuVo.setPath(menuDTO.getPath());
                        menuVo.setIFrame(menuDTO.getIFrame());
                        menuVo.setPermissions(menuDTO.getPermissions());
                        if (StringUtil.isNotBlank(menuVo.getPermissions())) {
                            menuVo.setIsMenu(false);

                        } else {
                            menuVo.setIsMenu(true);
                        }
                        menuVo.setSort(menuDTO.getSort());
                        // 如果不是外链
                        setComponent(menuDTO, menuVo);
                        menuVo.setMeta(new MenuMetaVo(menuDTO.getName(), menuDTO.getIcon()));
                        if (!Collections3.isEmpty(menuDTOList)) {
                            if (menuDTOList.size() > 0) {
                                menuVo.setAlwaysShow(true);
                                menuVo.setRedirect("noredirect");
                            }
                            menuVo.setChildren(buildMenus(menuDTOList));
                            // 处理是一级菜单并且没有子菜单的情况
                        } else if (menuDTO.getPid().equals(0L)) {
                            setChildren(menuDTO, menuVo);
                        }
                        //将name改为nameid
                        menuVo.setName(menuVo.getName() + "_" +  menuVo.getId());
                        list.add(menuVo);
                    }
                }
        );
        return list;
    }

    private static void setChildren(MenuDTO menuDTO, MenuVo menuVo) {
        MenuVo menuVo1 = new MenuVo();
        menuVo1.setMeta(menuVo.getMeta());
        // 非外链
        if (!menuDTO.getIFrame()) {
            menuVo1.setPath("index");
            menuVo1.setName(menuVo.getName());
            menuVo1.setComponent(menuVo.getComponent());
        } else {
            menuVo1.setPath(menuDTO.getPath());
        }
        menuVo.setName(null);
        menuVo.setMeta(null);
        menuVo.setComponent("Layout");
        List<MenuVo> list1 = new ArrayList<MenuVo>();
        list1.add(menuVo1);
        menuVo.setChildren(list1);
    }

    private static void setComponent(MenuDTO menuDTO, MenuVo menuVo) {
        if (!menuDTO.getIFrame()) {
            if (menuDTO.getPid().equals(0L)) {
                //一级目录需要加斜杠，不然访问 会跳转404页面
                menuVo.setPath("/" + menuDTO.getPath());
                menuVo.setComponent(StringUtil.isEmpty(menuDTO.getComponent()) ? "Layout" : menuDTO.getComponent());
            } else if (!StringUtil.isEmpty(menuDTO.getComponent())) {
                menuVo.setComponent(menuDTO.getComponent());
            }
        }
    }

    /**
     * like中的%转义处理
     * @param str
     * @return
     */
    public String like(String str){
        str = str.replace("%","\\\\%")
                .replace("_","\\\\_");
        logger.info("like处理转义后字符:{}",str);
        return  str;
    }

}
